#!/usr/bin/python3
# -*-coding:utf-8 -*-
"""
@Date   : 2020/3/19 16:11
@Author : jiangwm
@Desc   : 货币型: '6020-6020',(数量:920+)
        QDII型: '6020-6050',(数量:32+)
        封闭式" '6030-1010',(数量:260+)
        短期理财债券型: '6020-6060',(数量:100+)
"""
import os
import sys
os.chdir('../../..')
sys.path.insert(0, os.getcwd())

from retrying import retry
import datetime
import time
import json
import random
from quant_researcher.quant.datasource_fetch.basic_model.requests_model import MyRequest
import configparser
import re

class fund_netvalue_csrc:
    def __init__(self):
        self.fundNetvalue_log = None
        self.myRequest = None
        self.innerCode = None
        self.navdataQa = None

        self.headers = {
            'Accept': 'application/json, text/javascript, */*',
            'Accept-Encoding': 'gzip, deflate',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'Cache-Control': 'no-cache',
            'Content-Type': 'application/x-www-form-urlencoded',
            'DNT': '1',
            'Host': 'eid.csrc.gov.cn',
            'Origin': 'http://eid.csrc.gov.cn/fund/index.html',
            'Pragma': 'no-cache',
            'Referer': 'http://eid.csrc.gov.cn/fund/disclose/open_fund_daily_net.html?netDate=2019-12-24',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
            'X-Requested-With': 'XMLHttpRequest'
        }

    def ready_info(self):
        self.myRequest = MyRequest()

    @retry(stop_max_attempt_number=3)
    def fundNetvalue_trans(self):
        self.ready_info()

        try:
            # param: fundNet_json
            randomIndexTemp = random.uniform(0, 1)
            randomIndex = round(randomIndexTemp, 16)

            cookies_url = "http://eid.csrc.gov.cn/fund/index.html"
            get_cookies = self.myRequest.get_cookie(cookies_url)
            print(get_cookies)

            # 修改2
            #nowTime = datetime.datetime.now()
            nowTime = (datetime.datetime.now() + datetime.timedelta(days=-1))

            csrc_fundNet_dict = {
                "货币型": '6020-6020',
                "QDII型": '6020-6050',
                "封闭式": '6030-1010',
                "短期理财债券型": '6020-6060',
            }

            for fundNetItem in csrc_fundNet_dict.values():
                if fundNetItem == '6020-6050':
                    postData = {
                        "netDate": (nowTime + datetime.timedelta(days=-1)).strftime("%Y-%m-%d"),
                        "fundType": fundNetItem,
                    }
                else:
                    postData = {
                        "netDate": nowTime.strftime("%Y-%m-%d"),
                        "fundType": fundNetItem,
                    }

                startUrl = "http://eid.csrc.gov.cn/fund/disclose/daily_report_open_fund_daily_net.do?random={randomTime}".format(randomTime=randomIndex)
                startMessage = self.myRequest.post_dataJson_cookies(startUrl, self.headers, postData, get_cookies)

                response_messages = json.loads(startMessage)['dailyReportList']

                if response_messages:
                    for response_message in response_messages:
                        end_date = response_message.get('valuationDate') if response_message.get('valuationDate') else None

                        if end_date:
                            info_pubdate = (datetime.datetime.strptime(end_date, "%Y-%m-%d") + datetime.timedelta(days=+1)).strftime("%Y-%m-%d")

                        if end_date:
                            end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d").strftime("%Y%m%d")

                        fund_code = response_message.get('code') if response_message.get('code') else ''
                        fund_sname = response_message.get('shortName') if response_message.get('shortName') else ''
                        nav = response_message.get('shareNetValue') if response_message.get('shareNetValue') else None
                        accunav = response_message.get('totalNetValue') if response_message.get('totalNetValue') else None

                        # 每万份基金已实现收益 gainPer
                        # &&&需要进行单位转换---与标准库单位一致(万份收益)
                        return_pertt = response_message.get('gainPer') if response_message.get('gainPer') else None

                        if return_pertt != None:
                            if "每百份" in return_pertt:
                                return_pertt = float(return_pertt.replace('（每百份）', '').replace('（每百万份）', '')) * 100
                            elif "每百万份" in return_pertt:
                                return_pertt = float(return_pertt.replace('（每百份）', '').replace('（每百万份）', '')) / 100
                            elif return_pertt or return_pertt == "0" or return_pertt == "0.0000":
                                return_pertt = float(return_pertt)

                        # 7日年化收益率 yearSevenDayYieldRate
                        annu_yield = response_message.get('yearSevenDayYieldRate') if response_message.get('yearSevenDayYieldRate') else None
                        if annu_yield or annu_yield == "0.0000" or annu_yield == '0':
                            annu_yield = float(annu_yield) * 100

                        if nav or nav == "0.0000" or nav == '0':
                            nav = float(nav)

                        if accunav or accunav == "0.0000" or accunav == '0':
                            accunav = float(accunav)

                        if fundNetItem == '6020-6020':
                            if annu_yield or annu_yield==0:
                                if nav:
                                    pass
                                else:
                                    nav = float(1)
                            if annu_yield or annu_yield == 0:
                                if accunav:
                                    pass
                                else:
                                    accunav = float(1)

                        timestamp = lambda: int(time.time() * 1000000)

                        center_data = {
                            "fund_code": fund_code,
                            "fund_sname": fund_sname,
                            "special_sign": '1',
                            "nav": nav,
                            "currency": 'CNY',
                            "accunav": accunav,
                            "return_pertt": return_pertt,
                            "annu_yield": annu_yield,
                            "end_date": end_date,
                            "info_pubdate": info_pubdate,
                            "tdatachannel": "zjh",
                            "titime": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                            "tutime": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                            "tutimestamp": timestamp()
                        }

                        # judge the data in table
                        checkData = self.mongodb_end_center.findOne(self.end_collection, {"fund_code": fund_code, "end_date": end_date})
                        checkStatusData = self.mongodb_end_center.findOne(self.check_collection,
                                                                    {"fund_code": fund_code, "end_date": end_date})
                        if checkData:
                            # 分级基金优化：只保留分级基金信息
                            fundSname = checkData["fund_sname"]
                            fundSnameJudge = fundSname[-1]
                            judgeStatus = bool(re.search('[A-Z]', fundSnameJudge))

                            if judgeStatus:
                                pass
                            else:
                                try:
                                    center_data.pop('titime')
                                    self.mongodb_end_center.updateOne(self.end_collection, {"fund_code": center_data["fund_code"], "end_date": center_data["end_date"]}, center_data)

                                    # 更新状态表
                                    if checkStatusData:
                                        if checkStatusData["nv_usourceid"] == 2:
                                            pass
                                        elif len(checkStatusData["update_detail"])==1 and checkStatusData["update_detail"][0]["nv_usourceid"] == 1:
                                            netTemp = {}
                                            netTemp["nv_usourceid"] = 1
                                            netTemp["nv_udate"] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                                            netTemp["nav"] = center_data["nav"]
                                            netTemp["accunav"] = center_data["accunav"]
                                            netTemp["return_pertt"] = center_data["return_pertt"]
                                            netTemp["annu_yield"] = center_data["annu_yield"]

                                            updateDict = {}
                                            updateDict["tuseqid"] = self.innerCode.generate('ods_mf_nvustatus_tuseqid')

                                            netTemp["torigdatabuid"] = updateDict["tuseqid"]

                                            updateDict["update_detail"] = [netTemp]

                                            try:
                                                self.mongodb_end_center.updateOne(self.check_collection, {"fund_code": center_data["fund_code"],
                                                                               "end_date": center_data["end_date"]}, updateDict)
                                            except:
                                                raise
                                except:
                                    continue
                        else:
                            if center_data["nav"] != None or center_data["accunav"] != None or center_data["return_pertt"] != None or center_data["annu_yield"] != None:
                                self.navdataQa.validator(center_data)
                                self.mongodb_end_center.insertOne(self.end_collection, center_data)
                                # 添加数据时，同步更新基金日净值状态表
                                self.updateNetStatus(self.check_collection, self.mongodb_end_center, center_data, self.innerCode)

                self.fundNetvalue_log.info("cycle {} is over...".format(fundNetItem))
            self.fundNetvalue_log.info("fundNetvalue_trans is over...")
        except Exception as err:
            self.fundNetvalue_log.info("Fault: err: '%s'" % err)
        finally:
            pass

    def updateNetStatus(self, collection, mongodb, netItem, inner):
        #功能描述：基金日净值更新状态记录
        try:
            # 无基金当日净值，则添加，否则更新状态字段
            start_firstMessage = mongodb.findOne(collection, {"fund_code": netItem["fund_code"], "end_date": netItem["end_date"]}, {"_id": 0})

            if start_firstMessage:
                updateTemp = start_firstMessage["update_detail"][0]
                if updateTemp["nav"] == netItem["nav"]:
                    mulit_check = 1
                else:
                    mulit_check = 0

                netTemp = {}
                netTemp["nv_usourceid"] = 1
                netTemp["nv_udate"] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                netTemp["nav"] = netItem["nav"]
                netTemp["accunav"] = netItem["accunav"]
                netTemp["return_pertt"] = netItem["return_pertt"]
                netTemp["annu_yield"] = netItem["annu_yield"]
                netTemp["torigdatabuid"] = updateTemp["tuseqid"]

                updateDict = {}
                updateDict["mulit_check"] = mulit_check
                updateDict["update_detail"] = [updateTemp, netTemp]
                try:
                    mongodb.updateOne(collection, {"fund_code": netItem["fund_code"], "end_date": netItem["end_date"]}, updateDict)
                except:
                    raise
            else:
                netCheck = {}
                timestamp = lambda: int(time.time() * 1000000)
                # 直接插入净值状态数据
                netCheck["fund_code"] = netItem["fund_code"]
                netCheck["end_date"] = netItem["end_date"]
                netCheck["info_pubdate"] = netItem["info_pubdate"]
                netCheck["nv_usourceid"] = 1
                netCheck["nv_udate"] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

                netCheckTemp = netCheck.copy()
                netCheckTemp.pop("fund_code")
                netCheckTemp.pop("end_date")
                netCheckTemp.pop("info_pubdate")
                netCheckTemp["nav"] = netItem["nav"]
                netCheckTemp["accunav"] = netItem["accunav"]
                netCheckTemp["return_pertt"] = netItem["return_pertt"]
                netCheckTemp["annu_yield"] = netItem["annu_yield"]

                netCheck["update_detail"] = [netCheckTemp]
                netCheck["titime"] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                netCheck["tutime"] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                netCheck["tutimestamp"] = timestamp()
                netCheck["tuseqid"] = inner.generate('ods_mf_nvustatus_tuseqid')
                netCheck["mulit_check"] = None

                netCheckTemp["torigdatabuid"] = netCheck["tuseqid"]

                try:
                    mongodb.insertOne(collection, netCheck)
                except:
                    raise
        except Exception as err:
            pass
        finally:
            pass

    def getStartTradeDate(self, curDateStr, num):
        qryLastFiveDayNavSql = "select trade_date from pub_tradedate where trdmkt_code='0101001' and date(trade_date) <= '{}'  order by trade_date desc limit {}".format(
            curDateStr, num)
        return

    def getTradeInfo(self):
        self.mysqldb_end_center.checkAndConnect()

        self.fundNetvalue_log.info("netvalueMain_trans is starting...")

        try:
            # 查询交易日时间
            nowDateStr = datetime.datetime.now().strftime('%Y%m%d')
            lastTradeDate = self.getStartTradeDate(nowDateStr, 2)

            if lastTradeDate:
                if nowDateStr in str(lastTradeDate):
                    self.fundNetvalue_log.info("The {} is in trading day!".format(nowDateStr))
                    cf = configparser.ConfigParser()
                    cachePath = os.getcwd() + '/job/publicFund/fund_perform/cache_netValue.ini'
                    cf.read(cachePath, encoding='UTF-8')
                    navFPStartTime = cf.get('tradeDate', 'navFPStartTime')
                    navFPEndTime = cf.get('tradeDate', 'navFPEndTime')
                    navFPEachStamp = cf.get('tradeDate', 'navFPEachStamp')
                    navNFPEachStamp = cf.get('tradeDate', 'navNFPEachStamp')
                    endTime = cf.get('timeStatus', 'endTime')

                    nowTimeStr = datetime.datetime.now().strftime('%Y-%m-%d')

                    netTradeStart = nowTimeStr + ' ' + navFPStartTime
                    netTradeEnd = nowTimeStr + ' ' + navFPEndTime

                    endTimeStatus = nowTimeStr + ' ' + endTime

                    return [netTradeStart, netTradeEnd, endTimeStatus, int(navFPEachStamp), int(navNFPEachStamp)]

                else:
                    # 非交易日---基金净值
                    self.fundNetvalue_log.info("The {} is not in trading day!".format(nowDateStr))
                    nowTimeStr = datetime.datetime.now().strftime('%Y-%m-%d')

                    cf = configparser.ConfigParser()
                    cachePath = os.getcwd() + '/job/fund_datas/cache_netValue.ini'
                    cf.read(cachePath, encoding='UTF-8')
                    navPEachStamp = cf.get('notTradeDate', 'navPEachStamp')

                    endTime = cf.get('timeStatus', 'endTime')

                    endTimeStatus = nowTimeStr + ' ' + endTime

                    return [endTimeStatus, int(navPEachStamp)]

            self.fundNetvalue_log.info("netvalueMain_trans is over...")
        except Exception as err:
            self.fundNetvalue_log.info("Fault: err: '%s'" % err)
        finally:
            self.mysqldb_end_center.close()


if __name__ == '__main__':
    result_fundNetvalue = fund_netvalue_csrc()
    judgeTradeList = result_fundNetvalue.fundNetvalue_trans()
    #print(judgeTradeList)

    # 修改3
    result_fundNetvalue.fundNetvalue_trans()
    '''
    if judgeTradeList:
        if len(judgeTradeList) > 2:
            while True:
                nowTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                if nowTime < judgeTradeList[0]:
                    result_fundNetvalue.fundNetvalue_trans()
                    time.sleep(judgeTradeList[4])
                elif nowTime > judgeTradeList[0] and  nowTime < judgeTradeList[1]:
                    result_fundNetvalue.fundNetvalue_trans()
                    time.sleep(judgeTradeList[3])
                elif nowTime > judgeTradeList[1] and nowTime < judgeTradeList[2]:
                    result_fundNetvalue.fundNetvalue_trans()
                    time.sleep(judgeTradeList[4])
                elif nowTime > judgeTradeList[2]:
                    break
        else:
            while True:
                nowTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                result_fundNetvalue.fundNetvalue_trans()
                if nowTime > judgeTradeList[0]:
                    break
                time.sleep(judgeTradeList[1])
    '''
